package com.wh1200.mybatis.xmlless

import com.wh1200.mybatis.xmlless.annotations.criteria.Criteria
import com.wh1200.mybatis.xmlless.model.ClassInfo
import com.wh1200.mybatis.xmlless.model.JoinObjectInfo
import com.wh1200.mybatis.xmlless.model.base.BaseAnnotatedElementWrapper
import org.apache.ibatis.type.TypeHandler
import java.lang.reflect.Type

/**
 *
 * @author 吴昊
 * @date 2024/1/16 18:19
 * @since v0.0.0
 * @version 1.0
 */
object ElementInfoBuilder {

  private val CACHE = mutableMapOf<Any, AnnotatedElementDetailInfo>()

  fun build(
      element: BaseAnnotatedElementWrapper
  ): AnnotatedElementDetailInfo {
    if (CACHE.containsKey(element.getElement())) {
      return CACHE[element.getElement()]!!
    }
    val value = AnnotatedElementDetailInfo(element)
    CACHE[element.getElement()] = value
    return value
  }

  fun clearCache() {
    CACHE.clear()
  }

}


/**
 * @author 吴昊
 * @date 2024/01/15
 * @version 1.0
 * @since v4.0.0
 */
class AnnotatedElementDetailInfo(
    val element: BaseAnnotatedElementWrapper
) {

  val typeInfo: ClassInfo = element.getTypeInfo()
  val isString: Boolean = element.isString()
  val isCollection: Boolean = element.isCollection()
  val isPrimitive: Boolean = element.isPrimitive()
  val chooseCriteria = element.getChooseCriteria()
  val name = element.getName()
  val specificName: String? = element.getSpecificName()
  val paramName: String = (specificName ?: "").ifBlank { name }
  val isNotNull: Boolean = element.isNotNull()
  val testTypes = element.getParameterTestTypeList()
  val isNoIfWrap = element.isNoIfWrap()
  val isNotBlank: Boolean = element.isNotBlank()
  val isVersion: Boolean = element.isVersion()
  val isNotEmpty: Boolean = element.isNotEmpty()
  val criteria: Criteria? = element.getCriteria()
  val isJsonMappingProperty: Boolean = element.isJsonMappingProperty()
  val isCount: Boolean = element.isCount()
  val isInsertIgnore: Boolean = element.isInsertIgnore()
  val isSelectIgnore: Boolean = element.isSelectIgnore()
  val isAutoGeneratedKey: Boolean = element.isAutoGenerateKey()
  val isUpdateIgnore: Boolean = element.isUpdateIgnore()
  val update: String? = element.getUpdate()
  val handler: Class<out TypeHandler<*>>? = element.getCustomTypeHandlerClass()
  val handlerName: String? = element.getTypeHandlerName()
  val genericType: Type = element.getGenericType()
  val propertyMapTo: String = element.getPropertyMapTo()

  fun getJoinObjects(): List<JoinObjectInfo> {
    return element.getJoinPropertyList()
  }

  override fun hashCode(): Int {
    return element.getElement().hashCode()
  }

  override fun equals(other: Any?): Boolean {
    if (other !is AnnotatedElementDetailInfo) {
      return false
    }
    return this.element.getElement() == other.element.getElement()
  }

}
